package com.iotechn.unimall.app.api.seckill;

import com.iotechn.unimall.core.annotation.HttpMethod;
import com.iotechn.unimall.core.annotation.HttpOpenApi;
import com.iotechn.unimall.core.annotation.HttpParam;
import com.iotechn.unimall.core.annotation.HttpParamType;
import com.iotechn.unimall.core.annotation.param.NotNull;
import com.iotechn.unimall.core.exception.RepeatKillException;
import com.iotechn.unimall.core.exception.SeckillCloseException;
import com.iotechn.unimall.core.exception.SeckillException;
import com.iotechn.unimall.core.exception.ServiceException;
import com.iotechn.unimall.data.domain.SeckillSkuDO;
import com.iotechn.unimall.data.domain.SeckillSpuDO;
import com.iotechn.unimall.data.dto.goods.SpuDTO;
import com.iotechn.unimall.data.dto.order.OrderRequestDTO;
import com.iotechn.unimall.data.dto.seckill.*;
import com.iotechn.unimall.data.dto.goods.GroupShopDTO;
import com.iotechn.unimall.data.model.Page;

import java.math.BigDecimal;
import java.rmi.ServerException;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * 业务接口：应该站在"使用者"的角度设计，比如：
 * 1.定义方法的颗粒度要细
 * 2.方法的参数要明确且简练，不建议用类似Map这种让使用者封装一堆参数传递过来
 * 3.方法的return类型，除了要明确返回值类型，还应该指定该方法可能抛出的异常
 *
 * @auther TyCoding
 * @date 2018/10/6
 */
@HttpOpenApi(group = "seckill", description = "秒杀服务")
public interface SeckillService {

    @HttpMethod(description = "获取秒杀商品列表")
    public Page<SeckillSpuDTO> getSeckillPage(
            @HttpParam(name = "pageNo", type = HttpParamType.COMMON, description = "页码", valueDef = "1") Integer pageNo,
            @HttpParam(name = "pageSize", type = HttpParamType.COMMON, description = "页码长度", valueDef = "20") Integer pageSize) throws ServerException;


    @HttpMethod(description = "获取当天开启的秒杀商品列表")
    public Page<Map<String,Object>> getSeckillPageToday(
            @HttpParam(name = "pageNo", type = HttpParamType.COMMON, description = "页码", valueDef = "1") Integer pageNo,
            @HttpParam(name = "pageSize", type = HttpParamType.COMMON, description = "页码长度", valueDef = "20") Integer pageSize,
            @HttpParam(name = "gmtStart", type = HttpParamType.COMMON, description = "秒杀开始时间") Date gmtStart) throws ServerException;

    @HttpMethod(description = "获取当天开启的秒杀商品数量")
    public Integer getSeckillCountToday() throws ServerException;


    @HttpMethod(description = "获取当天秒杀时间集合")
    public List<Date> getGmtStartList() throws ServerException;

    @HttpMethod(description = "获取当前时间最近的两个秒杀活动")
    public Map<String,Object> latelySeckillList() throws ServerException;


    @HttpMethod(description = "执行秒杀操作")
    public SeckillResult<SeckillExecution> executeSeckill(
            @HttpParam(name = "seckillId", type = HttpParamType.COMMON, description = "商品Id", valueDef = "1") Long seckillId,
            @HttpParam(name = "md5", type = HttpParamType.COMMON, description = "md5信息", valueDef = "1") String md5,
            @HttpParam(name = "money", type = HttpParamType.COMMON, description = "金额", valueDef = "1") Integer money,
            @HttpParam(name = "userId", type = HttpParamType.USER_ID, description = "用户信息", valueDef = "1") Long userId);
    /**
     * 获取某一条商品秒杀信息
     *
     * @param seckillId
     * @return
     */
    @HttpMethod(description = "获取详细信息")
    SeckillSkuDO findById(@HttpParam(name = "seckillId", type = HttpParamType.COMMON, description = "商品Id", valueDef = "1") Long seckillId,
                          @HttpParam(name = "userId", type = HttpParamType.USER_ID, description = "用户信息", valueDef = "1") Long userId
    );

    /**
     * 秒杀开始时输出暴露秒杀的地址
     * 否者输出系统时间和秒杀时间
     *
     * @param seckillId
     */
    @HttpMethod(description = "获取地址信息")
    Exposer exportSeckillUrl(@HttpParam(name = "seckillId", type = HttpParamType.COMMON, description = "商品Id", valueDef = "1") Long seckillId,
                             @HttpParam(name = "userId", type = HttpParamType.USER_ID, description = "用户信息", valueDef = "1") Long userId
    );

    @HttpMethod(description = "获取秒杀商品Sku列表")
    public SeckillSpuPlusDTO getSeckillSkuList(
            @NotNull @HttpParam(name = "seckillSpuId", type = HttpParamType.COMMON, description = "秒杀商品Id")Long seckillSpuId,
            @NotNull @HttpParam(name = "userId", type = HttpParamType.USER_ID, description = "用户id",valueDef = "-1")Long userId

    ) throws ServiceException;


    @HttpMethod(description = "提交秒杀订单")
    public String takeSeckillOrder(
            @NotNull @HttpParam(name = "orderRequest", type = HttpParamType.COMMON, description = "订单请求实例")OrderRequestDTO orderRequest,
            @NotNull @HttpParam(name = "channel", type = HttpParamType.COMMON, description = "订单提交渠道")String channel,
            @NotNull @HttpParam(name = "userId", type = HttpParamType.USER_ID, description = "userId")Long userId)  throws ServiceException;
}
